﻿#include <unistd.h>

#include <iostream>

#include "ZTcpClient.h"
#include "netif/xadapter.h"
#include "platform_config.h"
#include "xil_printf.h"
#include "lwip/init.h"
#include "lwip/inet.h"

#define LWIP_DHCP 0

#define DEFAULT_IP_ADDRESS	"10.10.1.10"
#define DEFAULT_IP_MASK		"255.255.255.0"
#define DEFAULT_GW_ADDRESS	"10.10.1.1"

static int complete_nw_thread;
static sys_thread_t main_thread_handle;

void main_thread(void *p);
extern void print_app_header();
extern void start_application();

#define THREAD_STACKSIZE 1024

netif server_netif;

static void print_ip(char *msg, ip_addr_t *ip) {
  xil_printf(msg);
  xil_printf("%d.%d.%d.%d\n\r", ip4_addr1(ip), ip4_addr2(ip),
             ip4_addr3(ip), ip4_addr4(ip));
}

static void print_ip_settings(ip_addr_t *ip, ip_addr_t *mask, ip_addr_t *gw) {
  print_ip("Board IP:       ", ip);
  print_ip("Netmask :       ", mask);
  print_ip("Gateway :       ", gw);
}

static void assign_default_ip(ip_addr_t *ip, ip_addr_t *mask, ip_addr_t *gw) {
  int err;

  xil_printf("Configuring default IP %s \r\n", DEFAULT_IP_ADDRESS);

  err = inet_aton(DEFAULT_IP_ADDRESS, ip);
  if (!err)
    xil_printf("Invalid default IP address: %d\r\n", err);

  err = inet_aton(DEFAULT_IP_MASK, mask);
  if (!err)
    xil_printf("Invalid default IP MASK: %d\r\n", err);

  err = inet_aton(DEFAULT_GW_ADDRESS, gw);
  if (!err)
    xil_printf("Invalid default gateway address: %d\r\n", err);
}

void network_thread(void *p) {

}

void main_thread(void *p) {
  /* initialize lwIP before calling sys_thread_new */
  lwip_init();

  /* any thread using lwIP should be created using sys_thread_new */
  // sys_thread_new("nw_thread", network_thread, NULL,
  // 		THREAD_STACKSIZE,
  // 		DEFAULT_THREAD_PRIO);

  /* the mac address of the board. this should be unique per board */
  u8_t mac_ethernet_address[] =
      {0x00, 0x0a, 0x35, 0x00, 0x01, 0x02};

  xil_printf("\n\r\n\r");
  xil_printf("------lwIP Socket Mode TCP Client Application------\r\n");

  /* Add network interface to the netif_list, and set it as default */
  if (!xemac_add(&server_netif, NULL, NULL, NULL, mac_ethernet_address,
                 PLATFORM_EMAC_BASEADDR)) {
    xil_printf("Error adding N/W interface\r\n");
    return;
  }

  netif_set_default(&server_netif);

  /* specify that the network if is up */
  netif_set_up(&server_netif);

  /* start packet receive thread - required for lwIP operation */
  assign_default_ip(&(server_netif.ip_addr), &(server_netif.netmask),
                    &(server_netif.gw));
  sys_thread_new("xemacif_input_thread",
                 (void(*)(void *)) xemacif_input_thread, &server_netif,
                 THREAD_STACKSIZE,
                 DEFAULT_THREAD_PRIO);

  //
  // print_ip_settings(&(server_netif.ip_addr), &(server_netif.netmask),
  //                   &(server_netif.gw));

  // xil_printf("\r\n");
  /* print all application headers */
  // print_app_header();
  // xil_printf("\r\n");
  /* start the application*/
  start_application();

  vTaskDelete(NULL);
}

int main() {
  // main_thread_handle = sys_thread_new("main_thread", main_thread, 0,
  //                                     THREAD_STACKSIZE,
  //                                     DEFAULT_THREAD_PRIO);

  ZTcpClient client{
      "10.10.1.10",
      "10.10.1.131",
      9966, [&](const std::string &data) {
        std::cout << data << std::endl;
        client.writeData(data.data(), data.size());
      }
  };

  vTaskStartScheduler();
}